/*****************************************************************************
 * ijksdl_codec_android_mediaformat_java.c
 *****************************************************************************
 *
 * Copyright (c) 2014 Bilibili
 * copyright (c) 2014 Zhang Rui <bbcallen@gmail.com>
 *
 * This file is part of ijkPlayer.
 *
 * ijkPlayer is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * ijkPlayer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with ijkPlayer; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "ijksdl_codec_android_mediaformat_java.h"


#include "j4a/class/android/media/MediaFormat.h"
#include "j4a/class/ohos/media/common/Format.h"
#include "j4au/class/java/nio/ByteBuffer.util.h"
#include "ijksdl_android_jni.h"
#include "ijksdl_codec_android_mediaformat_internal.h"
#include "ijksdl_inc_internal_android.h"
#include <jni.h>
#include <stdint.h>
#include <stdio.h>

typedef struct SDL_AMediaFormat_Opaque {
    jobject android_media_format;

    jobject android_byte_buffer;
} SDL_AMediaFormat_Opaque;

jobject SDL_AMediaFormatJava_getObject(JNIEnv * env, const SDL_AMediaFormat * thiz)
{
    if (!thiz || !thiz->opaque)
        return NULL;

    SDL_AMediaFormat_Opaque * opaque = (SDL_AMediaFormat_Opaque *)thiz->opaque;
    return opaque->android_media_format;
}

static jobject getAndroidMediaFormat(JNIEnv * env, const SDL_AMediaFormat* thiz) {
    if (!thiz)
        return NULL;

    SDL_AMediaFormat_Opaque * opaque = (SDL_AMediaFormat_Opaque *)thiz->opaque;
    if (!opaque)
        return NULL;

    return opaque->android_media_format;
}

static sdl_amedia_status_t SDL_AMediaFormatJava_delete(SDL_AMediaFormat* aformat)
{
    if (!aformat)
        return SDL_AMEDIA_OK;

    JNIEnv * env = NULL;
    if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) {
        ALOGE("%s: SetupThreadEnv failed", __func__);
        return SDL_AMEDIA_ERROR_UNKNOWN;
    }

    SDL_AMediaFormat_Opaque * opaque = (SDL_AMediaFormat_Opaque *)aformat->opaque;
    if (opaque) {
        SDL_JNI_DeleteGlobalRefP(env, &opaque->android_byte_buffer);
        SDL_JNI_DeleteGlobalRefP(env, &opaque->android_media_format);
    }

    SDL_AMediaFormat_FreeInternal(aformat);
    return SDL_AMEDIA_OK;
}

static bool SDL_AMediaFormatJava_getInt32(SDL_AMediaFormat* aformat, const char* name, int32_t * out)
{
    JNIEnv * env = NULL;
    if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) {
        ALOGE("%s: SDL_JNI_SetupThreadEnv: failed", __func__);
        return false;
    }

    jobject android_media_format = getAndroidMediaFormat(env, aformat);
    if (!android_media_format) {
        ALOGE("%s: getAndroidMediaFormat: failed", __func__);
        return false;
    }

    // jint ret = J4AC_MediaFormat__getInteger__withCString(env, android_media_format, name);

    jint ret = J4AC_ohos_media_common_Format__getIntValue__withCString(env, android_media_format, name);
    if (J4A_ExceptionCheck__catchAll(env)) {
        ALOGE("%s: CallIntMethod: failed", __func__);
        return false;
    }

    if (out)
        *out = ret;
    return true;
}

static void SDL_AMediaFormatJava_setInt32(SDL_AMediaFormat* aformat, const char* name, int32_t value)
{
    JNIEnv * env = NULL;
    if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) {
        ALOGE("%s: SDL_JNI_SetupThreadEnv: failed", __func__);
        return;
    }

    jobject android_media_format = getAndroidMediaFormat(env, aformat);
    if (!android_media_format) {
        ALOGE("%s: getAndroidMediaFormat: failed", __func__);
        return;
    }

    J4AC_ohos_media_common_Format__putIntValue__withCString(env, android_media_format, name, value);

    if (J4A_ExceptionCheck__catchAll(env)) {
        ALOGE("%s: CallVoidMethod: failed", __func__);
        return;
    }
}

static void SDL_AMediaFormatJava_setBuffer(SDL_AMediaFormat* aformat, const char* name, void* data, size_t size)
{

    char c[50];
    sprintf(c, "SDL_AMediaFormatJava_setBuffer %s 长度 %d", name, size);


    int ret = -1;
    JNIEnv * env = NULL;
    if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) {
        ALOGE("%s: SDL_JNI_SetupThreadEnv: failed", __func__);
        return;
    }

    SDL_AMediaFormat_Opaque * opaque = (SDL_AMediaFormat_Opaque *)aformat->opaque;
    jobject android_media_format = opaque->android_media_format;
    if (!opaque->android_byte_buffer) {
        opaque->android_byte_buffer = J4AC_ByteBuffer__allocateDirect__asGlobalRef__catchAll(env, size);
        if (!opaque->android_byte_buffer) {
            J4A_FUNC_FAIL_TRACE();
            return;
        }
    }



    ret = J4AC_ByteBuffer__assignData__catchAll(env, opaque->android_byte_buffer, data, size);



    if (ret < 0) {
        J4A_FUNC_FAIL_TRACE();
        return;
    }

    // J4AC_MediaFormat__setByteBuffer__withCString(env, android_media_format, name, opaque->android_byte_buffer);

    J4AC_ohos_media_common_Format__putObjectValue__withCString(env, android_media_format, name, opaque->android_byte_buffer);

//    jobject jo = J4AC_ohos_media_common_Format__getObjectValue__withCString(env, android_media_format, name);
//    uint8_t* data1 = J4AC_ByteBuffer__getDirectBufferAddress(env, jo);
//    if (data1) {

//        for (int i = 0; i < size; i++) {
//            char c[70];
//            sprintf(c, "SDL_AMediaFormatJava_setBuffer 数据设置成功 %d, %d", i, data1[i]);
//
//        }
//    }

    if (J4A_ExceptionCheck__catchAll(env)) {
        ALOGE("%s: call jmid_setByteBuffer: failed", __func__);
        return;
    }


}

static void setup_aformat(SDL_AMediaFormat * aformat, jobject android_media_format) {
    SDL_AMediaFormat_Opaque * opaque = aformat->opaque;
    opaque->android_media_format = android_media_format;

    aformat->func_delete = SDL_AMediaFormatJava_delete;
    aformat->func_getInt32 = SDL_AMediaFormatJava_getInt32;
    aformat->func_setInt32 = SDL_AMediaFormatJava_setInt32;
    aformat->func_setBuffer = SDL_AMediaFormatJava_setBuffer;
}

SDL_AMediaFormat * SDL_AMediaFormatJava_init(JNIEnv * env, jobject android_format)
{
    SDLTRACE("%s", __func__);
    jobject global_android_media_format = (*env)->NewGlobalRef(env, android_format);
    if (J4A_ExceptionCheck__catchAll(env) || !global_android_media_format) {
        return NULL;
    }

    SDL_AMediaFormat * aformat = SDL_AMediaFormat_CreateInternal(sizeof(SDL_AMediaFormat_Opaque));
    if (!aformat) {
        SDL_JNI_DeleteGlobalRefP(env, &global_android_media_format);
        return NULL;
    }

    setup_aformat(aformat, global_android_media_format);
    return aformat;
}

SDL_AMediaFormat * SDL_AMediaFormatJava_createVideoFormat(JNIEnv * env, const char * mime, int width, int height)
{

    SDLTRACE("%s", __func__);

    // jobject android_media_format = J4AC_MediaFormat__createVideoFormat__withCString__asGlobalRef__catchAll(env, mime, width, height);

    jobject android_media_format = J4AC_ohos_media_common_Format__Format__asGlobalRef__catchAll(env);



    if (J4A_ExceptionCheck__catchAll(env) || !android_media_format) {
        return NULL;
    }



    char c[50];
    sprintf(c, "SDL_AMediaFormatJava_createVideoFormat3 %d,%d", width, height);


    jstring value = NULL;
    value = (*env)->NewStringUTF(env, mime);

    J4AC_ohos_media_common_Format__putObjectValue__withCString(env, android_media_format, "mime", value);
    J4AC_ohos_media_common_Format__putIntValue__withCString(env, android_media_format, "width", width);
    J4AC_ohos_media_common_Format__putIntValue__withCString(env, android_media_format, "height", height);

    SDL_AMediaFormat * aformat = SDL_AMediaFormat_CreateInternal(sizeof(SDL_AMediaFormat_Opaque));
    if (!aformat) {
        SDL_JNI_DeleteGlobalRefP(env, &android_media_format);
        return NULL;
    }

    setup_aformat(aformat, android_media_format);
    SDL_AMediaFormat_setInt32(aformat, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, 0);
    return aformat;
}
